// 加载运行时依赖
// express：轻量的 HTTP 服务框架
// mysql2/promise：基于 Promise 的 MySQL 客户端（我们使用连接池以提高并发能力）
// dotenv：从 .env 文件加载环境变量到 process.env
const express = require('express');
const mysql = require('mysql2/promise');
require('dotenv').config(); 

// 创建 Express 应用实例
const app = express();

// PORT：HTTP 服务监听端口。优先使用 `.env` 中的配置，默认回退到 3001。
const PORT = process.env.PORT || 3001;

// dbPool 保存 MySQL 连接池实例。连接池会重用连接，相比每次请求创建新连接更适用于真实场景。
let dbPool;

/**
 * initDb - 使用环境变量初始化 MySQL 连接池。
 * 重要环境变量（见 .env 或 TEACHING_NOTES.md）：
 *  - DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME
 * 如果连接失败，仅记录错误日志（便于调试路由），不会阻止进程启动，方便课堂调试。
 */
async function initDb() {
  dbPool = mysql.createPool({
    host: process.env.DB_HOST || 'localhost',
    port: process.env.DB_PORT ? Number(process.env.DB_PORT) : 3306,
    user: process.env.DB_USER || 'root',
    password: process.env.DB_PASSWORD || '',
    database: process.env.DB_NAME || 'flower_db',
    waitForConnections: true,    // queue requests when no connection available
    connectionLimit: 10,         // max concurrent connections in the pool
    queueLimit: 0                // unlimited queueing (0 = no limit)
  });

  // 使用一个简单的验证查询检查数据库连通性。这样在启动期间可以尽早看到有用的日志信息，避免无声失败。
  try {
    // 'SELECT 1' is a no-op check that returns immediately on most DBs
    await dbPool.query('SELECT 1');
    console.log('DB connected');
  } catch (err) {
    // 如果数据库不可达（密码错误、未启动等），记录错误信息。
    // 这对学生来说是第一个有用的排查点。
    console.error('DB connection failed:', err.message);
  }
}

// 健康检查端点（Health check），用于确认 HTTP 服务可达
app.get('/health', (req, res) => {
  // 返回运行状态和 uptime 是常见的最小化健康响应
  res.json({ status: 'ok', uptime: process.uptime() });
});

/**
 * 调试路由：用于课堂上的冒烟测试。
 * 从 `users` 表最多返回 10 条记录，用于验证整条链路：
 *  - 应用代码能正常运行
 *  - 连接池能执行查询
 *  - 提供的 SQL 初始化脚本已正确导入
 *
 * 安全提示：此路由仅用于开发/教学示例，切勿在生产环境暴露类似调试接口。
 */
app.get('/api/debug/users', async (req, res) => {
  try {
    // 使用简单的 SELECT 避免副作用。dbPool.query 返回 [rows, fields]
    const [rows] = await dbPool.query(
      'SELECT id, nick_name, openid, created_at FROM users LIMIT 10'
    );
    res.json(rows);
  } catch (err) {
    // 返回 500 并携带错误信息，帮助学生排查问题
    res.status(500).json({ error: err.message });
  }
});

/**
 * start - 初始化数据库并启动 HTTP 服务。
 * 将初始化与监听分离，可以在服务开始接收请求前看到启动期的错误（例如 DB 连接问题）。
 */
async function start() {
  await initDb();
  app.listen(PORT, () => {
    console.log(`Server listening on port ${PORT}`);
  });
}

// 启动应用，并在未捕获的启动异常时打印日志后退出
start().catch(err => {
  console.error('Failed to start:', err);
  process.exit(1);
});
